#Binary parser RequiemHurts_XMlate

import os, sys
from Sanae3D.lib.ModelObject import Model3D
from Sanae3D.lib.StructReader import StructReader

class RequiemHurts_XM(Model3D):
    '''Replace 'RequiemHurts_XM' with a suitable name of your choice. Try to follow
    the standard: GameName_FormatExt'''
    
    def __init__(self, obj3D=None, outFile=None, inFile=None):
        
        super(RequiemHurts_XM,self).__init__("XM")
        self.obj3D = obj3D
        self.inFile = inFile
        self.outFile = outFile
        self.texList = {}
        self.matDict = {}
        self.matList = []
        
    def read_name(self, n):
        
        return self.inFile.read_string(n).strip("\x00")
    
    def export_textures(self):
        
        for i in range(len(self.matList)):
            matName = self.matList[i]
            texName = self.matDict[matName]
            self.create_material(i)
            self.add_material_name(i, matName)
            self.add_texture_name(i, texName)
            
            if self.texList.has_key(texName):
                offset = self.texList[texName]
                self.inFile.seek(offset)
                texType = self.inFile.read_string(2)
                if texType == "BM":
                    filesize = self.inFile.read_long()
                    texFile = open(texName, 'wb')
                    self.inFile.seek(offset)
                    texFile.write(self.inFile.read(filesize))
                    texFile.close()
            
    def parse_mesh(self, meshName):
        
        self.create_object(meshName)
        matName = self.read_name(64)
        texName = self.read_name(64)
        texMask = self.read_name(64)
        
        numVerts, unk1, texSize, unk3, texOff, unk4, \
                unk5 = self.inFile.read_long(7)
        
        if not matName in self.matList:
            self.matList.append(matName)
            self.matDict[matName] = texName
        
        if texOff:
            self.texList[texName] = texOff

        matNum = self.matList.index(matName)
        faces = []
        for i in range(numVerts * 3):
            #print self.inFile.tell()
            vx, vy, vz = self.inFile.read_float(3)
            nx, ny, nz = self.inFile.read_float(3)
            tu, tv = self.inFile.read_float(2)
            faces.append(i)
            
            self.create_vertex(meshName, i)
            self.add_coords(meshName, i, [vx, vy, vz])
            self.add_vert_uv(meshName, i, [tu, tv])
            self.add_vert_normals(meshName, i, [nx, ny, nz])
            if len(faces) == 3:
                faceNum = i / 3
                self.create_face(meshName, faceNum)
                self.add_face_verts(meshName, faceNum, faces)
                self.add_face_material(meshName, faceNum, matNum)
                faces = []
            
    def parse_file(self):
        '''Main parser method. Can be replaced'''
        
        modelName = self.read_name(64)
        unk, numMesh = self.inFile.read_long(2)
        print numMesh
        for i in range(numMesh):
            str1 = self.read_name(64) #frame name?
            str2 = self.read_name(64)
            self.inFile.seek(256, 1)
            unk2, numSubmesh, unk3, unk4 = self.inFile.read_long(4)
            unk5, unk6, unk7, unk8 = self.inFile.read_long(4)
            #check if any of them is null
            #battle raper has 4 additional ints
            if not (unk5 and unk6 and unk7 and unk8):
                self.inFile.seek(120, 1)
            else:
                self.inFile.seek(104, 1)
            self.inFile.read_float(16)
            self.inFile.read_float(16)
            self.inFile.read_float(16)
            print numSubmesh, self.inFile.tell()
            for j in range(numSubmesh):
                if numSubmesh > 1:
                    meshName = "%s[%d]" %(str2, j)
                else:
                    meshName = "%s" %str2
                self.parse_mesh(meshName)
                
        self.export_textures()
            
        
def read_file(path):
    '''Read the file'''
    
    openFile = StructReader(open(path, 'rb'))
    obj = RequiemHurts_XM(inFile=openFile)
    obj.parse_file()
    openFile.close()
    return obj

def write_file(path):
    
    pass

def definitions():
    '''Return the header, extension, and a description of the format'''
    
    return "", "XM", "Requiem Hurts XM"

if __name__ == '__main__':
    
    file1 = "m1000.xm"
    file2 = "m1000_a.xm"
    obj = read_file(file1)